package org.jetlinks.pro.things.impl.connector;

import lombok.AllArgsConstructor;
import org.jetlinks.core.message.ThingMessage;
import org.jetlinks.core.message.event.DefaultEventMessage;
import org.jetlinks.core.message.property.DefaultReportPropertyMessage;
import org.jetlinks.core.things.MetadataId;
import org.jetlinks.core.things.ThingId;
import org.jetlinks.pro.things.ThingsConnector;
import reactor.core.Disposable;
import reactor.core.Disposables;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.function.Function;


/**
 * 指定多个`连接器`,将这些连接器连接在一起
 *
 * @author zhouhao
 * @see ThingsConnector
 * @since 1.12
 */
@AllArgsConstructor
public class CompositeThingsConnector extends AbstractThingsConnector {

    private final List<ThingsConnector> connectors;

    /**
     * 当dispose时此方法被执行,可用于进行资源释放等操作
     */
    @Override
    protected void onDispose() {
        connectors.forEach(ThingsConnector::dispose);
    }

    /**
     * 连接到当前物的物模型.物实例ID由数据源生成. 通常用于批量连接处理,比如在物模版里配置规则,计算对应物实例
     * 当产生消息时,handler将被调用.可调用返回值的{@link Disposable#dispose()}来断开连接
     *
     * @param metadataId 物模型ID
     * @param handler    消息处理器
     * @return Disposable
     */
    @Override
    protected Disposable doConnectTo(MetadataId metadataId, Function<ThingMessage, Mono<Void>> handler) {
        Disposable.Composite disposable = Disposables.composite();
        //将连接器组合中的所有连接器执行连接动作
        for (ThingsConnector connector : connectors) {
            disposable.add(
                connector.connectTo(metadataId, handler)
            );
        }
        return disposable;
    }

    /**
     * 连接到指定物的物模型,当产生消息时,handler将被调用.可调用返回值的{@link Disposable#dispose()}来断开连接
     *
     * @param thingId    物ID
     * @param metadataId 物模型ID
     * @param handler    消息处理器
     * @return Disposable
     */
    @Override
    protected Disposable doConnectTo(ThingId thingId, MetadataId metadataId, Function<ThingMessage, Mono<Void>> handler) {
        Disposable.Composite disposable = Disposables.composite();
        //将连接器组合中的所有连接器执行连接动作
        for (ThingsConnector connector : connectors) {
            disposable.add(
                connector.connectTo(thingId, metadataId, handler)
            );
        }
        return disposable;
    }
}
